home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / CBMKNDX.C < prev    next >
Text File  |  1991-09-23  |  5KB  |  230 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)cbmkndx.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #ifdef AC_STDDEF
  11. #include <stddef.h>
  12. #endif
  13. #ifdef AC_STDLIB
  14. #include <stdlib.h>
  15. #endif
  16. #ifdef AC_STRING
  17. #include <string.h>
  18. #endif
  19.  
  20. /* library headers */
  21. #include <blkio.h>
  22. #include <btree.h>
  23.  
  24. /* local headers */
  25. #include "cbase_.h"
  26.  
  27. /* btree field definition list */
  28. static btfield_t btfldv[] = {
  29.     {
  30.         0,
  31.         0,
  32.         NULL,
  33.         BT_FASC
  34.     },
  35.     {
  36.         0,
  37.         sizeof(cbrpos_t),
  38.         cbrposcmp,
  39.         BT_FASC
  40.     },
  41. };
  42.  
  43. /*man---------------------------------------------------------------------------
  44. NAME
  45.      cbmkndx - create new cbase index
  46.  
  47. SYNOPSIS
  48.      #include <cbase.h>
  49.  
  50.      int cbmkndx(cbp, field, flags, filename)
  51.      cbase_t *cbp;
  52.      int field;
  53.      int flags;
  54.      char *filename;
  55.  
  56. DESCRIPTION
  57.      The cbmkndx function builds a new index for an existing cbase.
  58.      The field to be indexed for cbp is specified by field.  flags
  59.      values are constructed by bitwise OR-ing flags from the following
  60.      list:
  61.  
  62.      CB_FKEY        Field is a key.
  63.      CB_FUNIQ       Only for use with CB_FKEY.  Indicates
  64.                     that the keys must be unique.
  65.  
  66.      CB_FKEY is assumed, and it is not necessary to set it in flags.
  67.      filename is the name of the file where the index is to reside.
  68.  
  69.      cbmkndx does not return until the build is completed.
  70.  
  71.      cbmkndx will fail if one or more of the following is true:
  72.  
  73.      [CBELOCK]      cbp is not read-locked.
  74.      [EEXIST]       The named field is already a key.
  75.      [EEXIST]       A file by the specified name already exists.
  76.      [EINVAL]       cbp is not a valid cbase pointer.
  77.      [EINVAL]       field is not a valid field number for cbp.
  78.      [EINVAL]       flags contains an invalid field flag.
  79.      [EINVAL]       filename is the NULL pointer.
  80.  
  81. SEE ALSO
  82.      cbcreate, cbrmndx.
  83.  
  84. DIAGNOSTICS
  85.      Upon successful completion, a value of 0 is returned.  Otherwise,
  86.      a value of -1 is returned, and errno set to indicate the error.
  87.  
  88. ------------------------------------------------------------------------------*/
  89. #ifdef AC_PROTO
  90. int cbmkndx(cbase_t *cbp, int field, int flags, char *filename)
  91. #else
  92. int cbmkndx(cbp, field, flags, filename)
  93. cbase_t *cbp;
  94. int field;
  95. int flags;
  96. char *filename;
  97. #endif
  98. {
  99.     cbrpos_t    cbrpos    = NIL;        /* record position */
  100.     void *        key    = NULL;        /* key buffer address */
  101.     void *        rec    = NULL;        /* record buffer address */
  102.     int        ltype    = BT_UNLCK;    /* lock type */
  103.  
  104.     /* validate arguments */
  105.     if (!cb_valid(cbp)) {
  106.         errno = EINVAL;
  107.         return -1;
  108.     }
  109.     if (field < 0 || field >= cbp->fldc) {
  110.         errno = EINVAL;
  111.         return -1;
  112.     }
  113.     if (flags & !(CB_FFLAGS) || filename == NULL) {
  114.         errno = EINVAL;
  115.         return -1;
  116.     }
  117.  
  118.     /* check lock status */
  119.     ltype = cbgetlck(cbp);
  120.     switch (ltype) {
  121.     case CB_RDLCK:
  122.         ltype = BT_RDLCK;
  123.         break;
  124.     case CB_WRLCK:
  125.         ltype = BT_WRLCK;
  126.         break;
  127.     default:
  128.         errno = CBELOCK;
  129.         return -1;
  130.     }
  131.  
  132.     /* check if already index */
  133.     if (cbp->fldv[field].flags & CB_FKEY) {
  134.         errno = EEXIST;
  135.         return -1;
  136.     }
  137.  
  138.     /* set flags and filename */
  139.     cbp->fldv[field].flags = CB_FKEY | flags;
  140.     cbp->fldv[field].filename = filename;
  141.  
  142.     /* create new index */
  143.     btfldv[1].offset = btfldv[0].len = cbp->fldv[field].len;
  144.     btfldv[0].cmp = cbcmpv[cbp->fldv[field].type];
  145.     if (btcreate(filename, CBM, btfldv[0].len + sizeof(cbrpos_t), 2, btfldv) == -1) {
  146. #ifdef DEBUG
  147.         if (errno != EEXIST) CBEPRINT;
  148. #endif
  149.         return -1;
  150.     }
  151.     cbp->btpv[field] = btopen(filename, "r+", 2, btfldv);
  152.     if (cbp->btpv[field] == NULL) {
  153.         CBEPRINT;
  154.         return -1;
  155.     }
  156.     if (btlock(cbp->btpv[field], BT_WRLCK) == -1) {
  157.         CBEPRINT;
  158.         return -1;
  159.     }
  160.  
  161.     /* load index */
  162.     if (cbreccnt(cbp) == 0) {
  163.         return 0;
  164.     }
  165.     if (cbrecfirst(cbp) == -1) {
  166.         CBEPRINT;
  167.         return -1;
  168.     }
  169.     /* allocate record and key */
  170.     rec = calloc((size_t)1, cbrecsize(cbp));
  171.     if (rec == NULL) {
  172.         CBEPRINT;
  173.         errno = ENOMEM;
  174.         return -1;
  175.     }
  176.     key = calloc((size_t)1, cbp->fldv[field].len + sizeof(cbrpos_t));
  177.     if (key == NULL) {
  178.         CBEPRINT;
  179.         errno = ENOMEM;
  180.         return -1;
  181.     }
  182.     while (cbrcursor(cbp) != NULL) {
  183.         /* get record and position */
  184.         if (cbgetr(cbp, rec) == -1) {
  185.             CBEPRINT;
  186.             free(rec);
  187.             free(key);
  188.             return -1;
  189.         }
  190.         if (cbgetrcur(cbp, &cbrpos) == -1) {
  191.             CBEPRINT;
  192.             free(rec);
  193.             free(key);
  194.             return -1;
  195.         }
  196.         /* construct (key, record position) pair */
  197.         memcpy(key, (char *)rec + cbp->fldv[field].offset, cbp->fldv[field].len);
  198.         memcpy((char *)key + cbp->fldv[field].len, &cbrpos, sizeof(cbrpos_t));
  199.         /* insert key */
  200.         if (btinsert(cbp->btpv[field], key) == -1) {
  201.             CBEPRINT;
  202.             free(rec);
  203.             free(key);
  204.             return -1;
  205.         }
  206.         if (cbrecnext(cbp) == -1) {
  207.             CBEPRINT;
  208.             free(rec);
  209.             free(key);
  210.             return -1;
  211.         }
  212.     }
  213.     free(rec);
  214.     rec = NULL;
  215.     free(key);
  216.     key = NULL;
  217.  
  218.     /* give new index same lock type as rest */
  219.     if (btlock(cbp->btpv[field], BT_UNLCK) == -1) {
  220.         CBEPRINT;
  221.         return -1;
  222.     }
  223.     if (btlock(cbp->btpv[field], ltype) == -1) {
  224.         CBEPRINT;
  225.         return -1;
  226.     }
  227.  
  228.     return 0;
  229. }
  230.